﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using TCKQKL.Service.DataContract;
using TCKQKL.Service.Config;
using TCKQKL.Service.Contract;
using TCKQKL.DAL.IDAL;
using TCKQKL.DAL.DataFactory;
using System.Net.Security;
using System.Transactions;

namespace TCKQKL.Service.Implementation
{
    public class DataAccessClient
    {
        private IInvestor dalInvestor;
        private IOrdersBosc dalOrdersBosc;
        private IOrdersOnline dalOrdersOnline;
        private IStocksInfo dalStk;

        public StocksDataModel getStockInfoBySymbol(string symbol)
        {
            dalStk = TCKQKL.DAL.DataFactory.StocksInfoFactory.Create(Settings.DAL);
            dalStk.Open(Settings.CONFIGDB_ORACLE_CONN_STRING);
            try
            {
                return dalStk.getStockInfoBySymbol(symbol);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalStk.Close();
            }
        }

        public OrdersOnlineModel getOrderOriginal(int OrderId)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.GetOriginalOrder(OrderId);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }

        public OrdersOnlineModel GetMostRecentOrder(string AccountNo, string OrderSide, DateTime OpenDate, DateTime ExpireDate, string Symbol, string Price, int Quantity, string TypeCancel)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            try
            {
                dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);

                return dalOrdersOnline.GetMostRecentOrder(AccountNo, OrderSide, OpenDate, ExpireDate, Symbol, Price,Quantity, TypeCancel);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }

        public decimal getTradingAmountByAccountNo(string AccountNo)
        {
            dalInvestor = TCKQKL.DAL.DataFactory.InvestorFactory.Create(Settings.DAL);
            dalInvestor.Open(Settings.CONFIGDB_ORACLE_CONN_STRING);
            try
            {
                return getTradingAmountByInvestorId(dalInvestor.getInvestorData(AccountNo).investorId);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalInvestor.Close();
            }
        }

        private decimal getTradingAmountByInvestorId(decimal investorId)
        {
            dalInvestor = TCKQKL.DAL.DataFactory.InvestorFactory.Create(Settings.DAL);
            dalInvestor.Open(Settings.CONFIGDB_ORACLE_CONN_STRING);

            try
            {
                List<BankDataModel> banks = dalInvestor.getBankDataByInvestorId(investorId);
                decimal remainStart = dalInvestor.getRemain(investorId, DateTime.Now.Date);
                decimal tradingAmount = remainStart;

                foreach (BankDataModel bk in banks)
                {
                    foreach (TransDataModel tran in dalInvestor.getTransByInvestorId(investorId, dalInvestor.getTradingDate(), dalInvestor.getTradingDate()))
                    {
                        if (tran.IncreaseAmount > 0)
                            tradingAmount += tran.IncreaseAmount;
                        else if (tran.DecreaseAmount > 0)
                            tradingAmount -= tran.DecreaseAmount;
                    }
                    return tradingAmount - bk.blockAmount;
                }
                return 0;
            }
            catch 
            {
                throw;
            }
            finally
            {
                dalInvestor.Close();
            }
        }

        public int getTradingQuantityByStockCode(string AccountNo, string StockCode)
        {
            dalInvestor = TCKQKL.DAL.DataFactory.InvestorFactory.Create(Settings.DAL);
            dalInvestor.Open(Settings.CONFIGDB_ORACLE_CONN_STRING);
            try
            {
                return dalInvestor.getTradingQuantityByStockCode(AccountNo, StockCode);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalInvestor.Close();
            }

        }

        public decimal GetOrderFee(OrdersOnlineModel order)
        {
            dalOrdersBosc = TCKQKL.DAL.DataFactory.OrdersBoscFactory.Create(Settings.DAL);
            dalOrdersBosc.Open(Settings.CONFIGDB_ORACLE_CONN_STRING);
            try
            {
                return getOrderCost(order) * dalOrdersBosc.getOrderFee(order);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalOrdersBosc.Close();
            }

        }

        public bool IsEnoughMoney(OrdersOnlineModel order)
        {
            try
            {
                decimal totalCost = 0;
                List<OrdersOnlineModel> list = getPendingOrdersByAccountNo(order.AccountNo, "COMPLETED");
                foreach (OrdersOnlineModel item in list)
                {
                    if (item.OrderSide.Equals("BUY") && item.OrderType.Equals("PLACE"))
                        totalCost += getOrderCost(item) + GetOrderFee(item);
                    if (item.OrderSide.Equals("BUY") && item.OrderType.Equals("CHANGE"))
                    {
                        OrdersOnlineModel recentOrder = GetMostRecentOrder(item.AccountNo, item.OrderSide, item.OpenDate, item.ExpireDate, item.Symbol, item.Price, item.Quantity, "CANCEL");
                        if (recentOrder != null)
                            totalCost += getOrderCost(item) + GetOrderFee(item)
                                    - getOrderCost(recentOrder) - GetOrderFee(recentOrder);
                    }
                }
                totalCost += getOrderCost(order) + GetOrderFee(order);
                return getTradingAmountByAccountNo(order.AccountNo) >= totalCost;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public bool IsEnoughStock(string AccountNo, string Symbol, int Quantity)
        {
            try
            {
                decimal totalQtty = 0;
                List<OrdersOnlineModel> list = getPendingOrdersByAccountNo(AccountNo, "COMPLETED");
                foreach (OrdersOnlineModel item in list)
                    if (item.OrderSide.Equals("SELL") && item.OrderType.Equals("PLACE"))
                        totalQtty += item.Quantity;
                totalQtty += Quantity;
                return getTradingQuantityByStockCode(AccountNo, Symbol) >= totalQtty;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private decimal getOrderCost(OrdersOnlineModel order)
        {
            try
            {
                StocksDataModel stk = getStockInfoBySymbol(order.Symbol);
                decimal OrderPrice = stk.Ceiling;

                if (order.OrderClass.Equals("LO") && !order.OrderType.Equals("CHANGE"))
                    OrderPrice = Convert.ToDecimal(order.Price);

                return OrderPrice * order.Quantity * 1000;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        public int InsertNewOrder(OrdersOnlineModel order)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.InsertNewOrder(order);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }

        public List<OrdersOnlineModel> getOrderListByStatus(string Status)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.getOrderListByStatus(Status);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalOrdersOnline.Close();
            }
        }

        public List<OrdersOnlineModel> getOrderListByStatusAndAccountNo(string Status, string AccountNo)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.getOrderListByStatusAndAccountNo(Status, AccountNo);
            }
            catch
            {
                throw;
            }
            finally
            {
                dalOrdersOnline.Close();
            }
        }

        public List<OrdersOnlineModel> getPendingOrdersByAccountNo(string AccountNo, string CompletedStatus)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.getPendingOrdersByAccountNo(AccountNo, CompletedStatus);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dalOrdersOnline.Close();
            }
        }

        public List<OrdersOnlineModel> getOnlineOrdersDetail(string AccountNo, string OrderSide, string Symbol, string OrderSpec, string OrderClass, string OrderMode, DateTime TimeStamp, string Price, string OrderType, string OrderNo, int Quantity)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.getOrderListDetail(AccountNo, OrderSide, Symbol, OrderSpec, OrderClass, OrderMode, TimeStamp, Price, OrderType, OrderNo, Quantity);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }

        public int UpdateChangeOrder(int OrderPlacedId, string Price)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.UpdateChangeOrder(OrderPlacedId, Price);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }

        public int InsertChangeOrder(int OrderId, string OrderNo, DateTime TimeStamp, int Quantity, string Price, string OrderType)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.InsertChangeOrder(OrderId, OrderNo, TimeStamp, Quantity, Price, OrderType);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }
        public int InsertCancelOrder(int OrderId, string OrderNo, DateTime TimeStamp, int Quantity, string Price, string OrderType)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                return dalOrdersOnline.InsertChangeOrder(OrderId, OrderNo, TimeStamp, Quantity, Price, OrderType);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }

        public void DeleteOrderByOrdePlacerId(int OrderPlaceId)
        {
            dalOrdersOnline = TCKQKL.DAL.DataFactory.OrdersOnlineFactory.Create(Settings.SQLDAL);
            dalOrdersOnline.Open(Settings.CONFIGDB_SQL_ORDERS);
            try
            {
                dalOrdersOnline.DeleteOrderByOrdePlacerId(OrderPlaceId);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dalOrdersOnline.Close();
            }

        }

    }
}
